Align with latest version of WebRTC spec (#20832) * Remove test for getDefaultIceServers which is no longer in the WebRTC spec * Remove unneeded dependency on getUserMedia for testing WebRTC stats * Fix bug in reading stats on receiver The test was trying to read the stats on the receiver using the track from the sender rather than the receiver * Remove obsolete RTCMediaStreamStats tests * Align with latest set of mandatory to implement stats From https://w3c.github.io/webrtc-pc/webrtc.html#mandatory-to-implement-stats * Remove test for obsolete 'stream' stats * Remove RTCRtpParameters features removed from the spec * Align with removal of encodings as receiverparameters Also, use getTransceivers() rather than getReceivers() since stopped receivers aren't provided in getReceivers() * encodings is only for SenderParameters now * Align with specs on content of rtpencoding parameters * Remove abandonned datachannel priority attribute * Align with removal of rtcoauthcredential * Remove test for obsoleted RTCMediaStreamStats * Align with latest MTI stats hiearchy based on https://w3c.github.io/webrtc-pc/webrtc.html#mandatory-to-implement-stats
diff --git a/webrtc/RTCConfiguration-iceServers.html b/webrtc/RTCConfiguration-iceServers.html index 2ef99bf..1cbf1d6 100644 --- a/webrtc/RTCConfiguration-iceServers.html +++ b/webrtc/RTCConfiguration-iceServers.html
@@ -29,21 +29,14 @@ 4.2.2. RTCIceCredentialType Enum enum RTCIceCredentialType { - "password", - "oauth" - }; - - 4.2.3. RTCOAuthCredential Dictionary - dictionary RTCOAuthCredential { - required DOMString macKey; - required DOMString accessToken; + "password" }; 4.2.4. RTCIceServer Dictionary dictionary RTCIceServer { required (DOMString or sequence<DOMString>) urls; DOMString username; - (DOMString or RTCOAuthCredential) credential; + DOMString credential; RTCIceCredentialType credentialType = "password"; }; */ @@ -375,7 +368,7 @@ accessToken: '' } }] })); - }, 'with turns server, credentialType password, and RTCOauthCredential credential should throw InvalidAccessError'); + }, 'with turns server, credentialType password, and object credential should throw InvalidAccessError'); /* 4.3.2. To set a configuration @@ -393,102 +386,6 @@ }] })); }, 'with turns server, credentialType oauth, and string credential should throw InvalidAccessError'); - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: 'turns:turn.example.org', - credentialType: 'oauth', - username: 'user', - credential: { - macKey: 'mac', - accessToken: 'token' - } - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - - const server = iceServers[0]; - assert_array_equals(server.urls, ['turns:turn.example.org']); - assert_equals(server.credentialType, 'oauth'); - assert_equals(server.username, 'user'); - - const { credential } = server; - assert_equals(credential.macKey, 'mac'); - assert_equals(credential.accessToken, 'token'); - - }, `with turns server, credentialType oauth and RTCOAuthCredential credential should succeed`); - - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: ['turns:turn.example.org', 'stun:stun1.example.net'], - credentialType: 'oauth', - username: 'user', - credential: { - macKey: 'mac', - accessToken: 'token' - } - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - - const server = iceServers[0]; - assert_array_equals(server.urls, ['turns:turn.example.org', 'stun:stun1.example.net']); - assert_equals(server.credentialType, 'oauth'); - assert_equals(server.username, 'user'); - - const { credential } = server; - assert_equals(credential.macKey, 'mac'); - assert_equals(credential.accessToken, 'token'); - - }, `with both turns and stun server, credentialType oauth and RTCOAuthCredential credential should succeed`); - - // credential type validation is ignored when scheme name is stun - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: 'stun:stun1.example.net', - credentialType: 'oauth', - username: 'user', - credential: 'cred' - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - const server = iceServers[0]; - - assert_array_equals(server.urls, ['stun:stun1.example.net']); - assert_equals(server.credentialType, 'oauth'); - assert_equals(server.username, 'user'); - assert_equals(server.credential, 'cred'); - - }, 'with stun server, credentialType oauth, and string credential should succeed'); - - // credential type validation is ignored when scheme name is stun - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: 'stun:stun1.example.net', - credentialType: 'password', - username: 'user', - credential: { - macKey: '', - accessToken: '' - } - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - - const server = iceServers[0]; - assert_array_equals(server.urls, ['stun:stun1.example.net']); - assert_equals(server.credentialType, 'password'); - assert_equals(server.username, 'user'); - - const { credential } = server; - assert_equals(credential.macKey, ''); - assert_equals(credential.accessToken, ''); - - }, 'with stun server, credentialType password, and RTCOAuthCredential credential should succeed'); - /* Tested 4.3.2. To set a configuration diff --git a/webrtc/RTCPeerConnection-getDefaultIceServers.html b/webrtc/RTCPeerConnection-getDefaultIceServers.html deleted file mode 100644 index 4fdbdb8..0000000 --- a/webrtc/RTCPeerConnection-getDefaultIceServers.html +++ /dev/null
@@ -1,98 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>RTCPeerConnection.getDefaultIceServers</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> - 'use strict'; - - // Test is based on the following editor draft: - // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html - - /* - [Constructor(optional RTCConfiguration configuration)] - interface RTCPeerConnection : EventTarget { - static sequence<RTCIceServer> getDefaultIceServers(); - ... - }; - - dictionary RTCIceServer { - required (DOMString or sequence<DOMString>) urls; - DOMString username; - (DOMString or RTCOAuthCredential) credential; - RTCIceCredentialType credentialType = "password"; - }; - - dictionary RTCOAuthCredential { - required DOMString macKey; - required DOMString accessToken; - }; - - enum RTCIceCredentialType { - "password", - "oauth" - }; - */ - - test(() => { - const iceServers = RTCPeerConnection.getDefaultIceServers(); - - assert_true(Array.isArray(iceServers), - 'Expect iceServers to be an array'); - - // dictionary IDL cannot be tested automatically using idlharness - for(const server of iceServers) { - const { urls, username, credential, credentialType } = server; - - if(Array.isArray(urls)) { - for(const url of urls) { - assert_equals(typeof url, 'string', - 'Expect elements in urls array to be string'); - } - } else { - assert_equals(typeof urls, 'string', - 'Expect urls to be either string or array'); - } - - if(username !== undefined) { - assert_equals(typeof username, 'string', - 'Expect username to be either undefined or string'); - } - - assert_true(credentialType === 'password' || credentialType === 'oauth', - 'Expect credentialType to be either password or oauth') - - if(credential) { - if(typeof(credential) === 'object') { - const { macKey, accessToken } = credential; - assert_equals(typeof macKey, 'string', - 'Expect macKey to be string'); - - assert_equals(typeof accessToken, 'string', - 'Expect accessToken to be string'); - - } else { - assert_equals(typeof credential, 'string', - 'Expect credential to be either undefined, string, or RTCOauthCredential dictionary'); - } - } - } - - // Expect default ice servers to be accepted as valid configuration - const pc = new RTCPeerConnection({ iceServers }); - - // Only make sure there are same number of ice servers configured - // and not do any deep equality checking - assert_equals(pc.getConfiguration().iceServers.length, iceServers.length); - - }, 'RTCPeerConnection.getDefaultIceServers() should return array of RTCIceServer'); - - /* - Coverage Report - Since there is no steps involved and we are only checking basic call, - This is counted as 1 trivial test coverage. - - Tested 1 - Total 1 - */ -</script> diff --git a/webrtc/RTCPeerConnection-getStats.https.html b/webrtc/RTCPeerConnection-getStats.https.html index f39fd2c..ede0ab1 100644 --- a/webrtc/RTCPeerConnection-getStats.https.html +++ b/webrtc/RTCPeerConnection-getStats.https.html
@@ -82,7 +82,7 @@ const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); - const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + const stream = await getNoiseStream({audio: true}); t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); const [track] = stream.getTracks(); pc.addTransceiver(track); @@ -292,9 +292,6 @@ 'Expect video track stats to be found'); assert_equals(videoTrackStats.kind, 'video'); - - assert_true(mediaStreamStats.trackIds.include(audioTrackStats.id)); - assert_true(mediaStreamStats.trackIds.include(videoTrackStats.id)); } const onConnected = t.step_func(() => { diff --git a/webrtc/RTCPeerConnection-mandatory-getStats.https.html b/webrtc/RTCPeerConnection-mandatory-getStats.https.html index 50158d4..7da14cd 100644 --- a/webrtc/RTCPeerConnection-mandatory-getStats.https.html +++ b/webrtc/RTCPeerConnection-mandatory-getStats.https.html
@@ -24,12 +24,17 @@ "packetsLost", "jitter", "packetsDiscarded", + "framesDropped" ], RTCInboundRtpStreamStats: [ - "trackId", "receiverId", "remoteId", "framesDecoded", + "nackCount", + "framesReceived", + "bytesReceived", + "totalAudioEnergy", + "totalSamplesDuration" ], RTCRemoteInboundRtpStreamStats: [ "localId", @@ -40,10 +45,11 @@ "bytesSent" ], RTCOutboundRtpStreamStats: [ - "trackId", "senderId", "remoteId", "framesEncoded", + "nackCount", + "framesSent" ], RTCRemoteOutboundRtpStreamStats: [ "localId", @@ -54,6 +60,7 @@ "dataChannelsClosed", ], RTCDataChannelStats: [ + "label", "protocol", "dataChannelIdentifier", "state", @@ -62,35 +69,34 @@ "messagesReceived", "bytesReceived", ], - RTCMediaStreamStats: [ - "streamIdentifer", - "trackIds", + RTCMediaSourceStats: [ + "trackIdentifier", + "kind" + ], + RTCAudioSourceStats: [ + "totalAudioEnergy", + "totalSamplesDuration" + ], + RTCVideoSourceStats: [ + "width", + "height", + "framesPerSecond" ], RTCMediaHandlerStats: [ "trackIdentifier", - "remoteSource", - "ended", ], RTCAudioHandlerStats: [ - "audioLevel", ], RTCVideoHandlerStats: [ - "frameWidth", - "frameHeight", - "framesPerSecond", ], RTCVideoSenderStats: [ - "framesSent", ], RTCVideoReceiverStats: [ - "framesReceived", - "framesDecoded", - "framesDropped", - "partialFramesLost", ], RTCCodecStats: [ "payloadType", "codecType", + "mimeType", "clockRate", "channels", "sdpFmtpLine", @@ -98,7 +104,6 @@ RTCTransportStats: [ "bytesSent", "bytesReceived", - "rtcpTransportStatsId", "selectedCandidatePairId", "localCertificateId", "remoteCertificateId", @@ -108,12 +113,11 @@ "localCandidateId", "remoteCandidateId", "state", - "priority", "nominated", "bytesSent", "bytesReceived", "totalRoundTripTime", - "currentRoundTripTime", + "currentRoundTripTime" ], RTCIceCandidateStats: [ "address", @@ -141,7 +145,10 @@ "csrc": "RTCRtpContributingSourceStats", "peer-connection": "RTCPeerConnectionStats", "data-channel": "RTCDataChannelStats", - "stream": "RTCMediaStreamStats", + "media-source": { + audio: "RTCAudioSourceStats", + video: "RTCVideoSourceStats" + }, "track": { video: "RTCSenderVideoTrackAttachmentStats", audio: "RTCSenderAudioTrackAttachmentStats" @@ -166,10 +173,12 @@ const parents = { RTCVideoHandlerStats: "RTCMediaHandlerStats", RTCVideoSenderStats: "RTCVideoHandlerStats", + RTCVideoSourceStats: "RTCMediaSourceStats", RTCSenderVideoTrackAttachmentStats: "RTCVideoSenderStats", RTCVideoReceiverStats: "RTCVideoHandlerStats", RTCAudioHandlerStats: "RTCMediaHandlerStats", RTCAudioSenderStats: "RTCAudioHandlerStats", + RTCAudioSourceStats: "RTCMediaSourceStats", RTCSenderAudioTrackAttachmentStats: "RTCAudioSenderStats", RTCAudioReceiverStats: "RTCAudioHandlerStats", RTCReceivedRtpStreamStats: "RTCRtpStreamStats", diff --git a/webrtc/RTCPeerConnection-ondatachannel.html b/webrtc/RTCPeerConnection-ondatachannel.html index 46fe8e0..0343655 100644 --- a/webrtc/RTCPeerConnection-ondatachannel.html +++ b/webrtc/RTCPeerConnection-ondatachannel.html
@@ -255,7 +255,7 @@ const dc1 = pc1.createDataChannel('test', { ordered: false, maxRetransmits: 1, - protocol: 'custom', + protocol: 'custom' }); assert_equals(dc1.label, 'test'); diff --git a/webrtc/RTCPeerConnection-track-stats.https.html b/webrtc/RTCPeerConnection-track-stats.https.html index 42054ad..7c34422 100644 --- a/webrtc/RTCPeerConnection-track-stats.https.html +++ b/webrtc/RTCPeerConnection-track-stats.https.html
@@ -48,29 +48,7 @@ async_test(t => { const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - let track = tracks[0]; - stream = streams[0]; - pc.addTrack(track, stream); - return pc.getStats(); - })) - .then(t.step_func(report => { - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(streamStats != null, 'Has stats for stream'); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'addTrack() without setLocalDescription() yields media stream stats'); - async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); let track; getUserMediaTracksAndStreams(1) .then(t.step_func(([tracks, streams]) => { @@ -97,107 +75,6 @@ }, 'addTrack() with setLocalDescription() yields track stats'); async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - let track = tracks[0]; - stream = streams[0]; - pc.addTrack(track, stream); - return pc.createOffer(); - })) - .then(t.step_func(offer => { - return pc.setLocalDescription(offer); - })) - .then(t.step_func(() => { - return pc.getStats(); - })) - .then(t.step_func(report => { - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(streamStats != null, 'Has stats for stream'); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'addTrack() with setLocalDescription() yields media stream stats'); - - async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - let track; - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - track = tracks[0]; - stream = streams[0]; - pc.addTrack(track, stream); - return pc.createOffer(); - })) - .then(t.step_func(offer => { - return pc.setLocalDescription(offer); - })) - .then(t.step_func(() => { - return pc.getStats(); - })) - .then(t.step_func(report => { - let trackStats = findStatsByTypeAndId(report, 'track', track.id); - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(trackStats != null && streamStats != null, - 'Has stats for track and stream'); - assert_array_equals(streamStats.trackIds, [ trackStats.id ], - 'streamStats.trackIds == [ trackStats.id ]'); - validateRtcStats(report, trackStats); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'addTrack(): Media stream stats references track stats'); - - async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - let track; - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - track = tracks[0]; - stream = streams[0]; - stream.addTrack(track); - for (const track of stream.getTracks()) - pc.addTrack(track, stream); - return pc.createOffer(); - })) - .then(t.step_func(offer => { - return pc.setLocalDescription(offer); - })) - .then(t.step_func(() => { - return pc.getStats(); - })) - .then(t.step_func(report => { - let trackStats = findStatsByTypeAndId(report, 'track', track.id); - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(trackStats != null && streamStats != null, - 'Has stats for track and stream'); - assert_array_equals(streamStats.trackIds, [ trackStats.id ], - 'streamStats.trackIds == [ trackStats.id ]'); - validateRtcStats(report, trackStats); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'Media stream stats references track stats'); - - async_test(t => { const caller = new RTCPeerConnection(); t.add_cleanup(() => caller.close()); const callee = new RTCPeerConnection(); diff --git a/webrtc/RTCRtpParameters-encodings.html b/webrtc/RTCRtpParameters-encodings.html index 539b269..e1a6e62 100644 --- a/webrtc/RTCRtpParameters-encodings.html +++ b/webrtc/RTCRtpParameters-encodings.html
@@ -120,7 +120,6 @@ sendEncodings: [{ active: false, maxBitrate: 8, - maxFramerate: 25, rid: 'foo' }] }); diff --git a/webrtc/RTCRtpParameters-helper.js b/webrtc/RTCRtpParameters-helper.js index 17ecfba..d7653c3 100644 --- a/webrtc/RTCRtpParameters-helper.js +++ b/webrtc/RTCRtpParameters-helper.js
@@ -50,6 +50,11 @@ function validateSenderRtpParameters(param) { validateRtpParameters(param); + assert_array_field(param, 'encodings'); + for(const encoding of param.encodings) { + validateEncodingParameters(encoding); + } + assert_not_equals(param.transactionId, undefined, 'Expect sender param.transactionId to be set'); @@ -101,20 +106,10 @@ sequence<RTCRtpCodecParameters> codecs; }; - enum RTCDegradationPreference { - "maintain-framerate", - "maintain-resolution", - "balanced" - }; */ function validateRtpParameters(param) { assert_optional_string_field(param, 'transactionId'); - assert_array_field(param, 'encodings'); - for(const encoding of param.encodings) { - validateEncodingParameters(encoding); - } - assert_array_field(param, 'headerExtensions'); for(const headerExt of param.headerExtensions) { validateHeaderExtensionParameters(headerExt); @@ -131,13 +126,8 @@ /* dictionary RTCRtpEncodingParameters { - RTCDtxStatus dtx; boolean active; - RTCPriorityType priority; - RTCPriorityType networkPriority; - unsigned long ptime; unsigned long maxBitrate; - double maxFramerate; [readonly] DOMString rid; @@ -145,31 +135,10 @@ double scaleResolutionDownBy; }; - enum RTCDtxStatus { - "disabled", - "enabled" - }; - - enum RTCPriorityType { - "very-low", - "low", - "medium", - "high" - }; */ function validateEncodingParameters(encoding) { - assert_optional_enum_field(encoding, 'dtx', - ['disabled', 'enabled']); - assert_optional_boolean_field(encoding, 'active'); - assert_optional_enum_field(encoding, 'priority', - ['very-low', 'low', 'medium', 'high']); - assert_optional_enum_field(encoding, 'networkPriority', - ['very-low', 'low', 'medium', 'high']); - - assert_optional_unsigned_int_field(encoding, 'ptime'); assert_optional_unsigned_int_field(encoding, 'maxBitrate'); - assert_optional_number_field(encoding, 'maxFramerate'); assert_optional_string_field(encoding, 'rid'); assert_optional_number_field(encoding, 'scaleResolutionDownBy'); diff --git a/webrtc/RTCRtpReceiver-getParameters.html b/webrtc/RTCRtpReceiver-getParameters.html index 4be0e3b..7047ce7 100644 --- a/webrtc/RTCRtpReceiver-getParameters.html +++ b/webrtc/RTCRtpReceiver-getParameters.html
@@ -36,12 +36,11 @@ t.add_cleanup(() => pc.close()); pc.addTransceiver('audio'); const callee = await doOfferAnswerExchange(t, pc); - const param = callee.getReceivers()[0].getParameters(); + const param = callee.getTransceivers()[0].receiver.getParameters(); validateReceiverRtpParameters(param); assert_greater_than(param.headerExtensions.length, 0); assert_greater_than(param.codecs.length, 0); - assert_equals(param.encodings.length, 1); }, 'getParameters() with audio receiver'); promise_test(async t => { @@ -49,12 +48,11 @@ t.add_cleanup(() => pc.close()); pc.addTransceiver('video'); const callee = await doOfferAnswerExchange(t, pc); - const param = callee.getReceivers()[0].getParameters(); + const param = callee.getTransceivers()[0].receiver.getParameters(); validateReceiverRtpParameters(param); assert_greater_than(param.headerExtensions.length, 0); assert_greater_than(param.codecs.length, 0); - assert_equals(param.encodings.length, 1); }, 'getParameters() with video receiver'); promise_test(async t => { @@ -67,15 +65,9 @@ ] }); const callee = await doOfferAnswerExchange(t, pc); - const param = callee.getReceivers()[0].getParameters(); + const param = callee.getTransceivers()[0].receiver.getParameters(); validateReceiverRtpParameters(param); - assert_greater_than(param.headerExtensions.length, 0); assert_greater_than(param.codecs.length, 0); - assert_equals(param.encodings.length, 2, 'layer count must match'); - assert_equals(param.encodings[0].rid, "rid1", - 'simulcast rids must match'); - assert_equals(param.encodings[1].rid, "rid2", - 'simulcast rids must match'); }, 'getParameters() with simulcast video receiver'); </script>